<?php

namespace App\Models\Traits;

use Carbon\Carbon;
use App\Models\Search;
use App\Models\SeckillProduct;
use App\Models\Product;
use App\Models\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Rainsens\Dinglog\Facades\Dinglog;
use Brick\Math\RoundingMode;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Builder;

trait SeckillProductCacheTrait
{

	public static function seckillProductCacheKey()
	{
		return "seckill_product";
	}

	public static function seckillProductNewCacheKey()
	{
		return "seckill_product_new";
	}

	public static function seckillProductRank()
	{
		return "seckill_rank";
	}

	public static function seckillProductUnallowedAreaCacheKey($province)
	{
		return "seckill_product_unallowed_area_{$province}";
	}

	public static function seckillProductAliveCacheKey($sid)
	{
		return "seckill_product_alive_{$sid}";
	}

	public static function seckillProductQueueCacheKey($sid): string
	{
		return "seckill_product_queue_{$sid}";
	}

	public static function seckillProductNumberCacheKey($sid): string
	{
		return "seckill_product_number_{$sid}";
	}

	public static function userSeckillCount($uid,$sid): string
	{
		return "user_{$uid}_seckill_{$sid}";
	}

	public static function sIsInSoldCache($sid)
	{
		return Redis::get(self::seckillProductNumberCacheKey($sid)) > 0 ? true : false;
	}

	public static function sIsInCache($sid)
	{
		return Redis::exists(self::seckillProductAliveCacheKey($sid));
	}

	public static function sBuyFromCache($uid, $sid)
	{
		$cacheId = '';
		Redis::decr(self::seckillProductNumberCacheKey($sid));
		Redis::rpop(self::seckillProductQueueCacheKey($sid));
		
		if (!SeckillProduct::sIsInSoldCache($sid)) {

			if(self::getNew($sid)){

				Redis::zRem(self::seckillProductNewCacheKey(), $sid);
				Redis::zAdd(self::seckillProductNewCacheKey(),999999,$sid);
			}else{
				Redis::zRem(self::seckillProductCacheKey(), $sid);
				Redis::zAdd(self::seckillProductCacheKey(),999999,$sid);

			}
			
		}

		$cacheId = User::sAddSeckilOrderToUnpaidCache($uid, $sid);

		/*Redis::transaction(function () use ($uid, $sid) {
			
			dd($cacheId);
			return $cacheId;
		});*/
		return $cacheId;
	}

	

	/**
	 * Clean all gold products cache.
	 */
	public static function cleanAllCache()
	{
		Redis::del(self::seckillProductCacheKey());
		self::all()->each(function (SeckillProduct $product) {
			$product->cleanCache();
		});
	}

	public function cleanCache()
	{
		Redis::del(self::seckillProductNumberCacheKey($this->id));
		Log::info("seckill product: {$this->id} cache cleaned");
	}


	public static function initCache()
	{

		Log::info("========== Start clean seckill cache ......");
		SeckillProduct::cleanAllCache();
        Log::info("========== seckill cache cleaned ......");

        Log::info("========== Start make seckill cache ......");
        SeckillProduct::makeAllCache();
		Log::info("========== seckill cache ready ......");
	}

	/**
	 * Cache all gold products in all gold rounds to redis.
	 */
	public static function makeAllCache()
	{
		self::where("saled_at",Carbon::today())->each(function (SeckillProduct $product) {

			$product->addToCache();
		});
	}

	public function addToCache()
	{
		
		if ($this->seckill_count == 0)
		{
			$this->cleanCache();
			return;
		}

		if(self::sIsInSoldCache($this->id)){
			Redis::del(self::seckillProductNumberCacheKey($this->id));
		}
		
		for($i=1; $i<=$this->seckill_count; $i++ ){
			Redis::incr(self::seckillProductNumberCacheKey($this->id));
		}
		
		Redis::zAdd(self::seckillProductCacheKey(), 1, $this->id );

		Log::debug("seckill: {$this->id} self added to cached");
	}

	

	public static function getProducts($source,$keyword=null)
	{	
		
		$key = url()->full();
		$products = Cache::remember($key, 1, function () use ($source,$keyword) {
			if($source == 'tomorrow'){

				$now = Carbon::tomorrow();
			}else{

				$now = Carbon::today();
			}


			if($source == 'ice'){
				$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice')->where(function (Builder $query) {
						$query->where('products.is_ice',true)->orWhere('products.is_low',true);
					})->with('product')->where('products.is_sale',true)->whereNull('products.deleted_at')->inRandomOrder()->paginate();

			}elseif($source  == 'rewards'){

				$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice')->where('products.is_higher_rewards',true)->where('products.is_sale',true)->whereNull('products.deleted_at')->with('product')->inRandomOrder()->paginate();
			}elseif($source == "quality"){

				$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice')->where('products.is_quality',true)->where('products.is_sale',true)->whereNull('products.deleted_at')->with('product')->inRandomOrder()->paginate();
			}elseif($source == "pop"){

				$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice')->where('products.is_pop',true)->where('products.is_sale',true)->whereNull('products.deleted_at')->with('product')->inRandomOrder()->paginate();

			}else{

				if($keyword){

					$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice')->where('products.title_long', 'like', "%$keyword%")->whereNull('products.deleted_at')->with('product')->where('products.is_sale',true)->orderbyDesc('products.is_rec')->orderbyDesc('seckill_products.id')->paginate();
					//dd(123);
					//if(request()->user()){
						//dd(123);
						Search::recordSearchToCache($keyword);
					//}
				}else{
					$products = SeckillProduct::join('products', 'products.id','seckill_products.product_id')->select('seckill_products.*','products.is_ice','products.is_sale','products.is_rec')->where('products.is_sale',true)->whereNull('products.deleted_at')->with('product')->orderbyDesc('products.is_rec')->inRandomOrder()->paginate();

				}

				
			}

			
			
			return $products;
		});
		//dd($products);
		//$result = [];

		/*$nowTime = time();
		foreach($products as &$product){
			$number = Redis::get(self::seckillProductNumberCacheKey($product->id));
			$res = [
				'rate'=> 0,
				'seckill_count'=>$number,
				'seckill_count_all' =>$product->seckill_count_all,
				'limit' => $product->seckill_count_all * 10,
				'saled_at' => $product->saled_at,
				'sid' =>$product->id,
				'start_rate' => $product->start_rate,
				'end_rate' => $product->end_rate,
				'incr_rate' => $product->incr_rate,
				'product'=>$product->product->toArray(),
				

			];
			$res['product']['skus'] = $product->product->skus->toArray();
  
			if($res['seckill_count'] <= 0){

				$res['rate'] = 100; 
			}else{

				$startTime = date("Y-m-d",time()).' '.cs("sale")->start_at;
				$startTime = strtotime($startTime);
				$endTime = date("Y-m-d",time()).' '.cs("sale")->end_at;
				$endTime = strtotime($endTime);


				if($nowTime > $startTime && $nowTime < $endTime){
					$incr = round(($nowTime - $startTime) / $res['incr_rate']);

					$finalRate = $res['start_rate'] + $incr;
					$res['rate'] = $finalRate > $res['end_rate']  ? (int)$res['end_rate'] : (int)$finalRate;

				}
			}

			$product = $res;

			//$result[] = $res;

		}*/
		return $products;
	}

	
	
}
